package com.example.fw;

import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;

import com.example.obj.ContactObject;
import com.example.obj.ContactSet;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ContactHelper extends HelperBase {
	
	private static ContactSet contactCache;

	public ContactHelper(ApplicationManager manager) {
		super(manager);		
	}

	public ContactSet getContactsCache() {
		log.info("Get Contacts Cache");		
		if (contactCache == null){
			buildContactCache();
		}
		return contactCache;
	}
	
	private void buildContactCache() {
		contactCache = manager.getHibernateHelper().getContacts();		
	}

	public ContactSet getContactsUI(){
		log.info("Get Contacts from UI");
		manager.getNavigationHelper().openContactListPage();
		WebElement table = findElement(By.id(manager.getProperty("contactsTable", "maintable")));
		List<WebElement> checkboxes = findElements(table, By.name(manager.getProperty("contactsCheckbox", "selected[]")));
		ContactSet contacts = new ContactSet();
		for (WebElement checkbox : checkboxes) {
			// i get value in outer (): [^\(]*\((.*)\)
			// i'm going to identify contact by FirstName + LastName
			// i suppose first "space" is the splitter between them: ([^ ]*)[ ]?(.*)
			// it's not always correct but concatenation gives me correct result later
			String firstName = "", lastName = "";
			Pattern p = Pattern.compile("[^\\(]*\\(([^ ]*)[ ]?(.*)\\)");
			Matcher m = p.matcher(checkbox.getAttribute(manager.getProperty("contactsName", "title")));			
			if (m.matches()){
				firstName = m.group(1);
				lastName = m.group(2);
			}
			ContactObject contact = new ContactObject()
				.setId(checkbox.getAttribute(manager.getProperty("contactsId", "value")))
				.setFirstName(firstName)
				.setLastName(lastName);
			contacts.add(contact);				
		}	
		return contacts;
	}
	
	public void createContact(ContactObject contactObject) {
		log.info("Add contact " + contactObject + " to the list");
		manager.getNavigationHelper().openContactListPage();
		initContactCreation();		
		fillContactData(contactObject);
		submitContactCreation();
		returnToContactList();
		buildContactCache();
	}
	
	public void deleteContact(String id) {
		log.info("Delete contact " + id + " from the list");
		manager.getNavigationHelper().openContactListPage();
		goToEditContactPage(id);
		submitContactDeletion();
		returnToContactList();
		buildContactCache();
	}

	public void modifyContact(String id, ContactObject contactObject) {
		log.info("Modify contact " + id + " to " + contactObject);
		manager.getNavigationHelper().openContactListPage();
		goToEditContactPage(id);		
		fillContactData(contactObject);
		submitContactModifying();
		returnToContactList();
		buildContactCache();
	}

	private void initContactCreation() {
		click(By.linkText(manager.getProperty("contactsAddNewLink", "add new")));
	}
	
	private void goToEditContactPage(String id) {
		click(By.cssSelector("a[href=\"edit.php?id=" + id + "\"]"));
	}
	
	private void fillContactData(ContactObject contactObject) {
		type(By.name("firstname"), contactObject.firstName);
		type(By.name("lastname"), contactObject.lastName);
		type(By.name("address"), contactObject.address);
		type(By.name("home"), contactObject.phoneHome);
		type(By.name("mobile"), contactObject.phoneMobile);
		type(By.name("work"), contactObject.phoneWork);
		type(By.name("email"), contactObject.email);
		type(By.name("email2"), contactObject.email2);
		selectValueFromTheList(By.name("bday"), contactObject.bday);
		selectValueFromTheList(By.name("bmonth"), contactObject.bmonth);		
		type(By.name("byear"), contactObject.byear);	
		if (isElementPresent(By.name("new_group"))){
			selectValueFromTheList(By.name("new_group"), contactObject.groupName);		
		}
		type(By.name("address2"), contactObject.address2);
		type(By.name("phone2"), contactObject.phone2);
	}
	
	private void submitContactCreation() {
		click(By.name(manager.getProperty("contactsSubmitNewButton", "submit")));		
	}
	
	private void submitContactDeletion() {
		click(By.xpath(manager.getProperty("contactsSubmitDelButton", "(//input[@name='update'])[2]")));
	}	
	
	private void submitContactModifying() {
		click(By.name(manager.getProperty("contactsSubmitUpdButton", "update")));		
	}
	
	private void returnToContactList() {
		click(By.linkText(manager.getProperty("contactsListReturnLink", "home page")));
	}
	
	public List<ContactObject> getPrintContacts(){
		manager.getNavigationHelper().openPrintPhonesPage();
		List<WebElement> cells = findElements(By.tagName("td"));	
		List<ContactObject> contacts =  new ArrayList<>();
		for (int i = 0; i < cells.size(); i++) {
			String[] contactFields = cells.get(i).getText().split("\n", 3);
			Pattern p = Pattern.compile("([^ ]*)[ ]?(.*):[^:]*");
			Matcher m = p.matcher(contactFields[0]);		
			if (m.matches()){ 
				ContactObject contact = new ContactObject()
					.setFirstName(m.group(1))
				 	.setLastName(m.group(2));
				if (contactFields.length > 1){
					p = Pattern.compile("H: (.*)");
					m = p.matcher(contactFields[1]);
					if (m.matches()){ contact.setPhoneHome(m.group(1)); }
				}
				contacts.add(contact);	
			}			
		}
		return contacts;
	}
	
	public List<ContactObject> getContactList() {
		manager.getNavigationHelper().openContactListPage();
		WebElement table = findElement(By.id(manager.getProperty("contactsTable", "maintable")));
		List<WebElement> rows = findElements(table, By.tagName("tr"));
		rows.remove(0); rows.remove(rows.size() - 1);
		List<ContactObject> contacts =  new ArrayList<>();
		for (WebElement row : rows) {
			List<WebElement> columns = findElements(row, By.tagName("td"));
			ContactObject contact = new ContactObject()
			// at the ContactList page headers 'Last Name' and 'First Name' are shown wrong 
//				.setFirstName(columns.get(1).getText())
//				.setLastName(columns.get(2).getText())
				.setFirstName(columns.get(2).getText())
				.setLastName(columns.get(1).getText())			
				.setPhoneHome(columns.get(4).getText());
			contacts.add(contact);				
		}	
		return contacts;
	}

	public ContactSet getCacheCopy() {
		ContactSet contactsDB = manager.getContactHelper().getContactsCache();
		for (ContactObject contact : contactsDB.getElements()) {
			contact.setPhoneHome("");
		}
		buildContactCache();
		return contactsDB;		
	}

	public ContactObject getContactUI(String id) {
		manager.getNavigationHelper().openContactListPage();
		goToEditContactPage(id);		
		return getContactData();
	}

	private ContactObject getContactData() {
		ContactObject contact = new ContactObject()
			.setFirstName(findElement(By.name("firstname")).getAttribute("value"))
			.setLastName(findElement(By.name("lastname")).getAttribute("value"))
			.setPhoneHome(findElement(By.name("home")).getAttribute("value"));
		return contact;
	}

}
